﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Meechisoft.TFS.BranchIndicator
{
    using EnvDTE;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Interop;
    using System.Windows.Media;

    public sealed class VSWindow
    {
        private System.Windows.Window window;
        private System.Windows.Controls.Border titlebar;
        private Type MainWindowToolBarType = null;
        private readonly System.Windows.Media.Brush originalTitleBarBrush;
        private readonly System.Windows.Media.Brush originalTitleBarFontBrush;
        private readonly IntPtr Handle;

        public VSWindow(DTE dte)
        {
            this.Handle = (IntPtr)dte.MainWindow.HWnd;
            this.window = GetWpfMainWindow();
            this.titlebar = FindTitleBar();
            if (this.titlebar != null)
            {
                this.originalTitleBarBrush = titlebar.Background;
                this.originalTitleBarFontBrush = GetTitleBarFontBrush();
            }
        }


        private System.Windows.Controls.Border FindTitleBar()
        {
            if (window == null)
                return null;

            if (MainWindowToolBarType == null)
                MainWindowToolBarType = window.GetType()
                    .Assembly
                    .GetType(String.Format("{0}.{1}", window.GetType().Namespace, "MainWindowTitleBar"));

            if (MainWindowToolBarType == null)
                return null;

            return FindChildItemsNoRecursion(MainWindowToolBarType, window, false).FirstOrDefault() as System.Windows.Controls.Border;
        }

        private UIElement RecurseChildControls(FrameworkElement parent)
        {
            if (parent == null)
                return null;

            foreach (object o in LogicalTreeHelper.GetChildren(parent))
            {
                if (MainWindowToolBarType.IsAssignableFrom(o.GetType()))
                    return o as System.Windows.UIElement;

                var ret = RecurseChildControls(o as FrameworkElement);
                if (ret != null)
                    return ret;
            }

            return null;
        }

        private static IEnumerable<DependencyObject> FindChildItemsNoRecursion(Type type, DependencyObject parent, bool many)
        {
            if (parent == null) yield break;

            var stillToProcess = new Queue<DependencyObject>();
            var childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (var i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                stillToProcess.Enqueue(child);
            }

            while (stillToProcess.Count > 0)
            {
                var childItem = stillToProcess.Dequeue();
                if (childItem != null)
                {
                    if (type.IsAssignableFrom(childItem.GetType()))
                    {
                        yield return childItem;
                        if (!many)
                            yield break;
                    }

                    var subchildrenCount = VisualTreeHelper.GetChildrenCount(childItem);
                    for (int i = 0; i < subchildrenCount; i++)
                    {
                        var child = VisualTreeHelper.GetChild(childItem, i);
                        stillToProcess.Enqueue(child);
                    }
                }
            }
        }


        public System.Windows.Window GetWpfMainWindow()
        {
            if (this.Handle == IntPtr.Zero)
                return null;

            var hwndSource = HwndSource.FromHwnd(this.Handle);
            if (hwndSource == null)
                return null;

            return hwndSource.RootVisual as System.Windows.Window;
        }

        public void Reset()
        {
            if (window == null)
                return;

            window.Dispatcher.InvokeAsync(DoReset);
        }

        private void DoReset()
        {
            DoResetTitleBar();
            DoResetTitleFont();
        }

        public void ResetTitleBar()
        {
            if (titlebar == null)
                return;

            titlebar.Dispatcher.InvokeAsync(DoResetTitleBar);
        }

        private void DoResetTitleBar()
        {
            titlebar.Background = originalTitleBarBrush;
        }

        public void ResetTitleFont()
        {
            if (titlebar == null)
                return;

            titlebar.Dispatcher.InvokeAsync(DoResetTitleFont);
        }

        private void DoResetTitleFont()
        {
            ChangeTitleFont(originalTitleBarFontBrush);
        }

        public void ChangeTitleBar(System.Windows.Media.Color colour, bool useGradient)
        {
            if (useGradient)
                titlebar.Dispatcher.InvokeAsync(() => titlebar.Background = CreateGradientBush(colour));
            else
                 titlebar.Dispatcher.InvokeAsync(() => titlebar.Background = new SolidColorBrush(colour));
        }

        private LinearGradientBrush CreateGradientBush(Color colour)
        {
            var originalColour = Colors.Transparent;

            if (originalTitleBarBrush is SolidColorBrush)
                originalColour = ((SolidColorBrush)originalTitleBarBrush).Color;

            var gradients = new GradientStopCollection();
            gradients.Add(new GradientStop(originalColour, 0));
            gradients.Add(new GradientStop(colour, 0.25));
            gradients.Add(new GradientStop(originalColour, 0.75));
            return new LinearGradientBrush(gradients);
        }

        public void ChangeTitleFont(System.Windows.Media.Color colour)
        {
            if (titlebar == null)
                return;

            titlebar.Dispatcher.InvokeAsync(()=> ChangeTitleFont(new SolidColorBrush(colour)));
        }

        private void ChangeTitleFont(System.Windows.Media.Brush brush)
        {
            foreach (TextBlock tb in FindChildItemsNoRecursion(typeof(TextBlock), titlebar, true))
            {
                if (tb.Text.Contains("Microsoft"))
                    tb.Foreground = brush;
            }
        }

        private System.Windows.Media.Brush GetTitleBarFontBrush()
        {
            foreach (TextBlock tb in FindChildItemsNoRecursion(typeof(TextBlock), titlebar, true))
            {
                if (tb.Text.Contains("Microsoft"))
                    return tb.Foreground;
            }

            return null;
        }

    }
}
